1.2 Go语言的特性与简洁性
在本节中,我们将从语言简洁性、并发支持以及内存管理三个方面来进行讲解。
这三个东西基本上算是 Go
语言最为显著的特性,也是与其他语言最大的区别。
语言简洁性
语法简洁明了
Go
语言的设计强调语言的简洁性,这是一开始就制定的原则,目标就是提高开发人员的开发效率,减少后续工程维护的工作量。Go
语言避免了很多冗余的关键字和语法结构。比如说Go
语言省略了class
的定义,使用更加直接的struct
以及接口来完成了面向对象编程。Go
语言简化了编程语法,去除了很多非必要的格式,比如去除了每一行代码结尾的分号,这其实在一定程度上可以避免很多问题。清晰的错误处理
Go
语言采用了显示的错误处理方式,不支持传统的try/catch
异常机制。Go
语言中,如果函数能够产生错误,那么都需要返回一个错误类型,这就会迫使开发者必须处理错误,从而提高代码的可靠性和可维护性。Go
语言中的错误处理其实存在一些争议,部分人会认为每一个调用都需要处理错误,这反而增加了开发工作量。笔者经过实践,我认为恰恰是这一特性,保证了
Go
语言代码在很大程度上更加健壮,通过错误处理我们的代码逻辑会更加严谨,BUG
会变得很少。代码格式统一
对于有实际工作经验的开发者来说,我们在每个团队基本都会遇到一个问题。那就是代码风格的统一,通常团队会制定一些规范手册、开发手册。
但是我们很少会看到关于
Go
语言的规范手册,这是因为Go
语言本身内置了gofmt
工具,用于格式化代码,确保所有代码都有一致的风格和格式。这在很大程度上消除了代码风格的争议,也使得从其他开发者的代码中学习或进行代码审查变得更加容易。
由于
Go
语言代码的简洁性,其实总共也就那么几种写法,所以基本上通过gofmt
就可以基本保证代码风格的统一了。
并发编程支持
原生的
goroutine
支持Go
语言为我们提供了轻量级的线程,也就是goroutine
协程。协程的加入让我们的并发编程变得异常简单。我们不需要进行创建、启动、回收的流程,我们只需要一个简单的关键字
go
就可以快速的启动协程进行并发操作。协程在运行的时候由
Go
的调度器进行动态管理,而不是由操作系统线程处理,这就降低了并发的复杂性及开销。在其他部分语言中,并发的时候就是创建线程,而创建的线程也是开销极大的,属于系统级线程,一般创建一个线程的开销就会在几百
KB
到MB
级别。而
Go
语言创建的协程其实并不是系统级线程,所以它的开销就被压的很低,初始创建一个协程时开销仅为2KB
,显著降低了并发的资源消耗。通道
Go
语言中的通道是一种内置的数据结构,可以在协程之间安全地传递数据。通过通道,开发者可以轻松地构建复杂的并发模式,如生产者-消费者模型,而无需担心数据竞争和锁问题。
通道的设计进一步提高了协程的可用性,同时也降低了开发难度,不用去担心协程通信的问题,协程通信在其他语言中可以说是很复杂的一个事情。
内存模型
Go
语言的内存模型为并发程序定义了清晰的规则,保证了在多线程环境下的内存安全。这减少了并发程序中常见的内存一致性错误。Go
语言的内存模型是一套复杂的东西,我们将在后续章节中进行讲解。
内存管理
自动垃圾回收(GC)
Go
语言实现了自动垃圾回收机制,这意味着开发者不需要手动管理内存分配和释放。GC
是并发执行的,并且在设计上力求减少应用程序的停顿时间,这对于需要高响应速度的应用程序尤其重要。内存逃逸分析
Go
语言编译器的一个重要特性是内存逃逸分析,它可以决定变量应该分配在栈上还是堆上。这种分析有助于优化内存使用,减少
GC
压力,并提升程序性能,可以让我们在编译阶段就提前发现一些问题,提高程序的稳定性及性能。
值和指针的明晰区分
Go
语言在值和指针之间提供了明确的区分,这有助于开发者更好地理解数据是如何在应用程序中流动的,也使得内存访问更加高效。Go
语言中,我们不需要像其他语言一样费劲的去理解指针,可以很轻松的就进行使用,同时使用时也并不容易出错。